From 1600c40500c674f8ed258164a11874a14764c629 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Mon, 28 Jul 2003 13:17:58 +0000 Subject: [PATCH] bitkeeper revision 1.376 (3f252286eVnrMT7PgP5t-QqVhRZAwQ) traps.c, hypervisor-if.h: Allow virtualisation of interrupt gates as well as task gates. If the appropriate flag is sent to set_trap_table then that exception causes the master event enable bit to be cleared in teh shared_info structure. --- xen/arch/i386/traps.c | 29 ++++++++++++++----- xen/include/hypervisor-ifs/hypervisor-if.h | 12 +++++--- .../arch/xeno/kernel/traps.c | 1 + 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/xen/arch/i386/traps.c b/xen/arch/i386/traps.c index 66e52c2456..119641767e 100644 --- a/xen/arch/i386/traps.c +++ b/xen/arch/i386/traps.c @@ -1,5 +1,5 @@ /* - * linux/arch/i386/traps.c + * xen/arch/i386/traps.c * * Copyright (C) 1991, 1992 Linus Torvalds * @@ -189,6 +189,7 @@ static void inline do_trap(int trapnr, char *str, struct pt_regs * regs, long error_code, int use_error_code) { + struct task_struct *p = current; struct guest_trap_bounce *gtb = guest_trap_bounce+smp_processor_id(); trap_info_t *ti; unsigned long fixup; @@ -201,6 +202,8 @@ static void inline do_trap(int trapnr, char *str, gtb->error_code = error_code; gtb->cs = ti->cs; gtb->eip = ti->address; + if ( TI_GET_IF(ti) ) + clear_bit(EVENTS_MASTER_ENABLE_BIT, &p->shared_info->events_mask); return; fault_in_hypervisor: @@ -274,6 +277,8 @@ asmlinkage void do_page_fault(struct pt_regs *regs, long error_code) gtb->error_code = error_code; gtb->cs = ti->cs; gtb->eip = ti->address; + if ( TI_GET_IF(ti) ) + clear_bit(EVENTS_MASTER_ENABLE_BIT, &p->shared_info->events_mask); return; /* @@ -371,6 +376,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, long error_code) asmlinkage void do_general_protection(struct pt_regs *regs, long error_code) { + struct task_struct *p = current; struct guest_trap_bounce *gtb = guest_trap_bounce+smp_processor_id(); trap_info_t *ti; unsigned long fixup; @@ -403,13 +409,11 @@ asmlinkage void do_general_protection(struct pt_regs *regs, long error_code) { /* This fault must be due to instruction. */ ti = current->thread.traps + (error_code>>3); - if ( ti->dpl >= (regs->xcs & 3) ) + if ( TI_GET_DPL(ti) >= (regs->xcs & 3) ) { gtb->flags = GTBF_TRAP_NOCODE; - gtb->cs = ti->cs; - gtb->eip = ti->address; regs->eip += 2; - return; + goto finish_propagation; } } @@ -417,8 +421,11 @@ asmlinkage void do_general_protection(struct pt_regs *regs, long error_code) ti = current->thread.traps + 13; gtb->flags = GTBF_TRAP; gtb->error_code = error_code; + finish_propagation: gtb->cs = ti->cs; gtb->eip = ti->address; + if ( TI_GET_IF(ti) ) + clear_bit(EVENTS_MASTER_ENABLE_BIT, &p->shared_info->events_mask); return; gp_in_kernel: @@ -718,16 +725,24 @@ long do_set_fast_trap(int idx) * The former range is used by Windows and MS-DOS. * Vector 0x80 is used by Linux and the BSD variants. */ - if ( (idx != 0x80) && ((idx < 0x20) || (idx > 0x2f)) ) return -1; + if ( (idx != 0x80) && ((idx < 0x20) || (idx > 0x2f)) ) + return -1; ti = current->thread.traps + idx; + /* + * We can't virtualise interrupt gates, as there's no way to get + * the CPU to automatically clear the events_mask variable. + */ + if ( TI_GET_IF(ti) ) + return -1; + CLEAR_FAST_TRAP(¤t->thread); current->thread.fast_trap_idx = idx; current->thread.fast_trap_desc.a = (ti->cs << 16) | (ti->address & 0xffff); current->thread.fast_trap_desc.b = - (ti->address & 0xffff0000) | 0x8f00 | (ti->dpl&3)<<13; + (ti->address & 0xffff0000) | 0x8f00 | (TI_GET_DPL(ti)&3)<<13; SET_FAST_TRAP(¤t->thread); diff --git a/xen/include/hypervisor-ifs/hypervisor-if.h b/xen/include/hypervisor-ifs/hypervisor-if.h index ab5ca7943a..adedd40607 100644 --- a/xen/include/hypervisor-ifs/hypervisor-if.h +++ b/xen/include/hypervisor-ifs/hypervisor-if.h @@ -146,12 +146,16 @@ /* * Send an array of these to HYPERVISOR_set_trap_table() */ +#define TI_GET_DPL(_ti) ((_ti)->flags & 3) +#define TI_GET_IF(_ti) ((_ti)->flags & 4) +#define TI_SET_DPL(_ti,_dpl) ((_ti)->flags |= (_dpl)) +#define TI_SET_IF(_ti,_if) ((_ti)->flags |= (_if)) typedef struct trap_info_st { - unsigned char vector; /* exception/interrupt vector */ - unsigned char dpl; /* privilege level */ - unsigned short cs; /* code selector */ - unsigned long address; /* code address */ + unsigned char vector; /* exception vector */ + unsigned char flags; /* 0-3: privilege level; 4: clear event enable? */ + unsigned short cs; /* code selector */ + unsigned long address; /* code address */ } trap_info_t; /* diff --git a/xenolinux-2.4.21-sparse/arch/xeno/kernel/traps.c b/xenolinux-2.4.21-sparse/arch/xeno/kernel/traps.c index e9c2fd5a1c..85c6acb8f0 100644 --- a/xenolinux-2.4.21-sparse/arch/xeno/kernel/traps.c +++ b/xenolinux-2.4.21-sparse/arch/xeno/kernel/traps.c @@ -554,6 +554,7 @@ static void __init set_call_gate(void *a, void *addr) } +/* NB. All these are "trap gates" (i.e. events_mask isn't cleared). */ static trap_info_t trap_table[] = { { 0, 0, __KERNEL_CS, (unsigned long)divide_error }, { 1, 0, __KERNEL_CS, (unsigned long)debug }, -- 2.30.2